﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.Threading.Channels;
namespace CurrentTest
{
    public struct DataBuffer
    {
        public double Value { get; set; }
        public double Filter { get; set; }
    }
    public partial class MainViewModel : ObservableObject
    {
        [ObservableProperty]
        private string[]? serialPortList;

        [ObservableProperty]
        [NotifyCanExecuteChangedFor(nameof(OpenCommand))]
        private string? portName;

        [ObservableProperty]
        private string? errorMessage;

        public Channel<DataBuffer> DataChannel = Channel.CreateUnbounded<DataBuffer>();

        [RelayCommand(CanExecute = nameof(CanModifySerialPort))]
        private async Task RefreshSerialPortList()
        {
            SerialPortList = await Task.Run(() =>
            {
                return SerialPort.GetPortNames();
            });
        }

        public bool CanModifySerialPort => !running;

        private bool running = false;
        private SerialPort? serialPort;

        private CancellationTokenSource? tokenSource;

        [RelayCommand(CanExecute = nameof(CanOpenSerialPort))]
        private async Task Open()
        {
            tokenSource = new();
            running = true;
            try
            {
                ErrorMessage = null;
                serialPort = new SerialPort { PortName = this.PortName, BaudRate = 500000, StopBits = StopBits.One, DataBits = 8, Parity = Parity.None };
                serialPort.Open();
                await ParseData(serialPort, tokenSource.Token);
            }
            catch(Exception ex)
            {
                ErrorMessage = ex.Message;
                serialPort?.Close();
            }
            running = false;
        }

        [RelayCommand]
        private void Close()
        {
            tokenSource?.Cancel();
        }

        private async Task ParseData(SerialPort port, CancellationToken token)
        {
            port.ReadTimeout = 100;
            bool first = true;
            int count = 0;
            await Task.Run(() =>
            {
                while (!token.IsCancellationRequested)
                {
                    try
                    {
                        string line = port.ReadLine();
                        var sArray = line.Split(',');
                        if(sArray.Count() == 2 && int.TryParse(sArray[0], out var current) && int.TryParse(sArray[1], out var filter))
                        {
                            if (first)
                            {
                                first = false;
                                continue;
                            }
                            while (!DataChannel.Writer.TryWrite(new DataBuffer { Value = current, Filter = filter})) ;
                        }
                    }
                    catch (Exception ex)
                    {
                        Thread.Sleep(1);
                    }
                }
            });
            
            port.Close();
        }


        public bool CanOpenSerialPort => !string.IsNullOrWhiteSpace(PortName);
    }
}
